package com.atlassian.jira.web.action.jimex;

import com.atlassian.jira.ComponentManager;
import com.atlassian.jira.ManagerFactory;
import com.atlassian.jira.config.SubTaskManager;
import com.atlassian.jira.config.ConstantsManager;
import com.atlassian.jira.exception.PermissionException;
import com.atlassian.jira.issue.Issue;
import com.atlassian.jira.issue.IssueImpl;
import com.atlassian.jira.issue.MutableIssue;
import com.atlassian.jira.issue.customfields.OperationContext;
import com.atlassian.jira.issue.fields.IssueTypeSystemField;
import com.atlassian.jira.issue.fields.ProjectSystemField;
import com.atlassian.jira.issue.fields.screen.FieldScreenRenderLayoutItem;
import com.atlassian.jira.issue.fields.screen.FieldScreenRenderTab;
import com.atlassian.jira.issue.fields.screen.FieldScreenRenderer;
import com.atlassian.jira.issue.operation.IssueOperation;
import com.atlassian.jira.issue.operation.IssueOperations;
import com.atlassian.jira.util.EasyList;
import com.atlassian.jira.web.action.issue.AbstractIssueSelectAction;
import com.atlassian.jira.web.action.issue.IssueCreationHelperBean;
import com.atlassian.jira.workflow.JiraWorkflow;
import com.atlassian.jira.workflow.WorkflowException;
import net.sf.jimex.jira.LinkType;
import org.ofbiz.core.entity.GenericValue;
import webwork.action.ActionContext;
import webwork.action.ServletActionContext;
import webwork.multipart.MultiPartRequestWrapper;

import java.util.*;

/**
 * andrew 09.03.2006 23:30:58
 */
public class JimexImportProject extends AbstractIssueSelectAction implements OperationContext {
    private Long pid;
    private SubTaskManager subTaskManager;
    private ConstantsManager constantsManager;

    public IssueOperation getIssueOperation() {
        return IssueOperations.CREATE_ISSUE_OPERATION;
    }

    private String issuetype;
    protected Map customFieldValuesHolder;
    protected MutableIssue issueObject;
    private Collection ignoreFieldIds;
    private SortedSet tabsWithErrors;
    private FieldScreenRenderer fieldScreenRenderer;
    private int selectedTab;
    private IssueCreationHelperBean issueCreationHelperBean;
    public static final String JIRA_USER_HISTORY_ISSUETYPE = "jira.user.history.issuetype";
    private Collection linkTypes;
    private Long linkType;


    public class ButtonHolder {

        public String getName() {
            return name;
        }

        public String getValue() {
            return value;
        }

        private final String name, value;

        public ButtonHolder(String name, String value) {
            this.name = name;
            this.value = value;
        }
    }

    public JimexImportProject(IssueCreationHelperBean issueCreationHelperBean, SubTaskManager subTaskManager, ConstantsManager constantsManager) {
        this.subTaskManager = subTaskManager;
        this.constantsManager = constantsManager;
        customFieldValuesHolder = new HashMap();
        selectedTab = 1;
        ignoreFieldIds = EasyList.build("issuetype");
        ignoreFieldIds.add("summary");
        ignoreFieldIds.add("duedate");
        ignoreFieldIds.add("assignee");
        ignoreFieldIds.add("reporter");
        ignoreFieldIds.add("environment");
        ignoreFieldIds.add("description");
        ignoreFieldIds.add("timetracking");
        this.issueCreationHelperBean = issueCreationHelperBean;
        linkTypes = LinkType.getLinkTypes();
    }

    public String doDefault() throws Exception {
        GenericValue current = null;
        try {
            current = getSelectedProject();
        }
        catch (PermissionException pe) {
            log.warn("You do not have the permission to browse the project currently s" +
                    "elected."
            );
        }
        if (current != null && pid == null && getAllowedProjects().contains(current)) {
            pid = current.getLong("id");
            getCustomFieldValuesHolder().put("project", pid);
        }

        return super.doDefault();
    }

    protected void setHistoryIssuetype() {
        if (issuetype == null) {
            issuetype = (String) ActionContext.getSession().get(JIRA_USER_HISTORY_ISSUETYPE);
        }
        if (issuetype == null) {
            issuetype = getApplicationProperties().getString("jira.constant.default.issue.type");
        }
        getCustomFieldValuesHolder().put("issuetype", issuetype);
    }

    public Collection getAllowedProjects()
            throws Exception {
        return ManagerFactory.getPermissionManager().getProjects(11, getRemoteUser());
    }


    public Long getPid() {
        return pid;
    }

    public void setPid(Long pid) {
        this.pid = pid;
    }

    public GenericValue getProject() {
        return getProjectManager().getProject(pid);
    }

    public String getIssuetype() {
        return issuetype;
    }

    public void setIssuetype(String issueType) {
        issuetype = issueType;
    }

    public Map getCustomFieldValuesHolder() {
        return customFieldValuesHolder;
    }

    protected String doExecute()
            throws Exception {
        ProjectSystemField projectField = (ProjectSystemField) getField("project");
        projectField.updateIssue(null, getIssueObject(), getCustomFieldValuesHolder());
        IssueTypeSystemField issueTypeField = (IssueTypeSystemField) getField("issuetype");
        issueTypeField.updateIssue(null, getIssueObject(), getCustomFieldValuesHolder());
        saveHistoryIssueType();
        setSelectedProjectId(getPid());
        populateFieldHolderWithDefaults(getIssueObject(), Collections.EMPTY_LIST);
        return "success";
    }

    protected void saveHistoryIssueType() {
        ActionContext.getSession().put(JIRA_USER_HISTORY_ISSUETYPE, issuetype);
    }

    protected String getHistoryIssueType() {
        return (String) ActionContext.getSession().get(JIRA_USER_HISTORY_ISSUETYPE);
    }

    protected void populateFieldHolderWithDefaults(Issue issue, Collection excludedFieldIds) {
        for (Iterator iterator = getFieldScreenRenderer().getFieldScreenRenderTabs().iterator(); iterator.hasNext();) {
            FieldScreenRenderTab fieldScreenRenderTab = (FieldScreenRenderTab) iterator.next();
            Iterator iterator1 = fieldScreenRenderTab.getFieldScreenRenderLayoutItems().iterator();
            while (iterator1.hasNext()) {
                FieldScreenRenderLayoutItem fieldScreenRenderTabLayoutItem = (FieldScreenRenderLayoutItem) iterator1.next();
                String fieldId = fieldScreenRenderTabLayoutItem.getOrderableField().getId();
                if (!excludedFieldIds.contains(fieldId) && !"project".equals(fieldId) && !"issuetype".equals(fieldId)) {
                    fieldScreenRenderTabLayoutItem.populateDefaults(getCustomFieldValuesHolder(), issue);
                }
            }
        }
    }

    public MutableIssue getIssueObject() {
        if (issueObject == null) {
            issueObject = new IssueImpl((GenericValue) null,
                    getIssueManager(),
                    getProjectManager(),
                    getVersionManager(),
                    ManagerFactory.getIssueSecurityLevelManager(),
                    getConstantsManager(),
                    ComponentManager.getInstance().getSubTaskManager(),
                    getAttachmentManager());
        }
        return issueObject;
    }

    protected void doValidation() {
        try {
            issueCreationHelperBean.validateProject(getIssueObject(), this, ActionContext.getParameters(), this, this);
            if (!invalidInput()) {
                getIssueObject().setProject(getProject());
            }
            issueCreationHelperBean.validateIssueType(getIssueObject(), this, ActionContext.getParameters(), this, this);
            if (!invalidInput()) {
                getIssueObject().setIssueTypeId(getIssuetype());
            }
        }
        catch (Exception e) {
            log.error(e, e);
            addErrorMessage("An exception occurred: " + e + ".");
        }
    }

    protected void validateIssueType() {
        IssueTypeSystemField issueTypeField = (IssueTypeSystemField) getField("issuetype");
        issueTypeField.populateFromParams(getCustomFieldValuesHolder(), ActionContext.getParameters());
        issueTypeField.validateParams(this, this, this, getIssueObject(), getFieldScreenRenderer().getFieldScreenRenderLayoutItem(issueTypeField));
    }

    public List getFieldScreenRenderTabs() {
        return getFieldScreenRenderer().getFieldScreenRenderTabs();
    }

    protected FieldScreenRenderer getFieldScreenRenderer() {
        if (fieldScreenRenderer == null) {
            fieldScreenRenderer = issueCreationHelperBean.createFieldScreenRenderer(getRemoteUser(), getIssueObject());
        }
        return fieldScreenRenderer;
    }

    private void initTabsWithErrors() {
        tabsWithErrors = new TreeSet();
        if (getErrors() != null && !getErrors().isEmpty()) {
            String fieldId;
            for (Iterator iterator = getErrors().keySet().iterator(); iterator.hasNext(); tabsWithErrors.add(fieldScreenRenderer.getFieldScreenRenderTabPosition(fieldId))) {
                fieldId = (String) iterator.next();
            }

            selectedTab = ((FieldScreenRenderTab) tabsWithErrors.first()).getPosition() + 1;
        } else {
            selectedTab = 1;
        }
    }

    public int getSelectedTab() {
        if (tabsWithErrors == null) {
            initTabsWithErrors();
        }
        return selectedTab;
    }

    public Collection getIgnoreFieldIds() {
        return ignoreFieldIds;
    }

    public List getCustomFields(Issue issue) {
        return getCustomFieldManager().getCustomFieldObjects(issue.getProject().getLong("id"), issue.getIssueType().getString("id"));
    }


    public List getButtons()
            throws WorkflowException {
        List buttons = new ArrayList();
        Map buttonAttrs = getWorkflowMetaAttributes();
        String key;
        String val;
        for (Iterator it = buttonAttrs.keySet().iterator(); it.hasNext(); buttons.add(new ButtonHolder(key, getText(val)))) {
            key = (String) it.next();
            val = (String) buttonAttrs.get(key);
        }

        return buttons;
    }

    private final Map getWorkflowMetaAttributes()
            throws WorkflowException {
        JiraWorkflow workflow = ManagerFactory.getWorkflowManager().getWorkflow(getPid(), getIssuetype());
        return workflow.getDescriptor().getInitialAction(1).getMetaAttributes();
    }

    public boolean isHasProjectPermission(int permissionsId, GenericValue project) {
        if (project == null) {
            throw new IllegalArgumentException("isHasProjectPermission can not be passed a null project");
        }
        if (!"Project".equals(project.getEntityName())) {
            throw new IllegalArgumentException("isHasProjectPermission can only take a Project: " + project.getEntityName() + " is not.");
        } else {
            return getPermissionManager().hasPermission(permissionsId, project, getRemoteUser(), true);
        }
    }

    public Collection getTabsWithErrors() {
        if (tabsWithErrors == null) {
            initTabsWithErrors();
        }
        return tabsWithErrors;
    }

    protected MultiPartRequestWrapper getMultipart() {
        return ServletActionContext.getMultiPartRequest();
    }

    public Collection getLinkTypes() {
        return linkTypes;
    }

    public Long getLinkType() {
        return linkType;
    }

    public void setLinkType(Long linkType) {
        this.linkType = linkType;
    }

    public boolean isSubTasksEnabled() {
        return subTaskManager.isSubTasksEnabled();
    }

    public ConstantsManager getConstantsManager() {
        return constantsManager;
    }

    public Collection getSubTasksIssueTypes() {
        Collection issueTypes = subTaskManager.getSubTasksIssueTypes();
        return issueTypes;
    }


    
}
